
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session;

import entities.Administrateur;
import entities.Client;
import entities.CompteCourant;
import entities.CompteEpargne;
import entities.OperationBancaire;
import java.util.List;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author ALAOUI_Pierre_CYWIER
 */
@Stateless
@LocalBean
public class GestionnaireDeCompteBancaire {

    @PersistenceContext(unitName = "BanqueCywierPierro-ejbPU")
    private EntityManager em;

    /*********
     * 
     * 
     *      Compte Courant
     * 
     * 
     * *******/
    // creation d'un compte courant
    public CompteCourant creerCompte(double solde) {
        CompteCourant compteCourant = new CompteCourant(solde);
        OperationBancaire op = new OperationBancaire("Création du compte", solde);
        compteCourant.getOperations().add(op);

        em.persist(compteCourant);


        return compteCourant;
    }

    // retourne une liste de tous les comptes courants
    public List<CompteCourant> getAllComptes() {
        Query q = em.createNamedQuery("CompteCourant.findAll");

        return q.getResultList();
    }

    public List<CompteCourant> getComptes(int start, int nbComptes) {
        Query q = em.createNamedQuery("CompteCourant.findAll");
        q.setFirstResult(start);
        q.setMaxResults(nbComptes);

        return q.getResultList();
    }

    public List<Client> getClients(int start, int nbComptes) {
        Query q = em.createNamedQuery("Client.findAll");
        q.setFirstResult(start);
        q.setMaxResults(nbComptes);

        return q.getResultList();
    }

    public List<CompteCourant> getComptes(int start, int nbComptes, String sortField, String sortOrder) {
        Query q;
        if (sortField == null) {
            q = em.createNamedQuery("CompteCourant.findAll");
        } else {
            q = em.createQuery("SELECT c FROM CompteCourant c ORDER BY c." + sortField + " " + sortOrder);
        }
        q.setFirstResult(start);
        q.setMaxResults(nbComptes);

        return q.getResultList();
    }

    public List<Client> getClients(int start, int nbComptes, String sortField, String sortOrder) {
        Query q;
        if (sortField == null) {
            q = em.createNamedQuery("Client.findAll");
        } else {
            q = em.createQuery("SELECT c FROM Client c ORDER BY c." + sortField + " " + sortOrder);
        }
        q.setFirstResult(start);
        q.setMaxResults(nbComptes);

        return q.getResultList();
    }

    public List<OperationBancaire> getOperations(int start, int nbComptes, String sortField, String sortOrder) {
        Query q;
        if (sortField == null) {
            q = em.createNamedQuery("CompteCourant.findAll");
        } else {
            q = em.createQuery("SELECT c FROM CompteCourant c ORDER BY c." + sortField + " " + sortOrder);
        }
        q.setFirstResult(start);
        q.setMaxResults(nbComptes);

        return q.getResultList();
    }

    public int getCount() {
        return Integer.parseInt(em.createNamedQuery("CompteCourant.count").getSingleResult().toString());
    }

    // retourne un compte courant portant l'id 
    public CompteCourant getCompteById(Long id) {
        try {
            return (CompteCourant) em.createNamedQuery("CompteCourant.findById").setParameter("id", id).getSingleResult();
        } catch (Exception e) {
            System.err.println("Le compte n'existe pas");
            return null;
        }
    }

    // retourne un compte courant portant l'id 
    public CompteEpargne getCompteEpargneById(Long id) {
        CompteEpargne compteEpargne = em.find(CompteEpargne.class, id);
        return compteEpargne;
    }

    public CompteCourant getCompteBySolde(Double solde) {
        try {
            return (CompteCourant) em.createNamedQuery("CompteCourant.findBySolde").setParameter("soldeCompte", solde).getSingleResult();
        } catch (Exception e) {
            System.err.println("Le compte n'existe pas");
            return null;
        }
    }

    // methode de test pr creer plusieurs comptes courant
    public void creerComptesTest() {


        // creation de clients avec leurs compte courants

        creerClient("John", "Lennon", "rue", "lo", "pa", 3);
        creerClient("Peter", "Lennon", "rue", "ppe", "peet", 8);
        creerClient("Charles", "KK", "rue", "sed", "deg", 78);
        creerClient("Po", "Ty", "rue", "po", "eet", 1500);

        creerClient("nim", "chaki", "rue", "mi", "flint", 3);
        creerClient("carl", "onu", "rue", "ma", "haa", 8);
        creerClient("hola", "tic", "rue", "toto", "toto", 78);
        creerClient("nico", "tac", "rue", "papi", "chou", 1500);




        creerClient("Kimberly", "Len", "349-2503 Tellus Avenue", "Maxwell", "Daryl", 941);
        creerClient("Iona", "Dexter", "927-7212 Consequat Street", "Moore", "Robin", 1093);
        creerClient("Louis", "Armando", "209-723 Fermentum St.", "Blackburn", "Ruth", 972);
        creerClient("Whilemina", "Wang", "6868 Orci, Road", "Emerson", "Noelle", 936);
        creerClient("Brody", "Flynn", "8263 Magna Road", "Oconnor", "Odette", 1063);
        creerClient("Ferdinand", "Jermaine", "Ap #993-1423 Ut, Avenue", "Solis", "Brianna", 959);

        Client client = creerClient("Nshimiyimana", "Pierre", "22 rue Assalit", "kanana", "pierro", 123);
        associerCompteEpargneClient(client.getId(), 2000, 2);

        Client client1 = creerClient("Amine", "ALAOUI", "valrose", "amine", "slifer", 100000);
        associerCompteEpargneClient(client1.getId(), 2000, 2);

        Client client2 = creerClient("Helene", "Lennon", "rue", "xed", "ez", 1250);
        associerCompteEpargneClient(client2.getId(), 2000, 2);





        creerAdministrateur("alaoui", "amine", "yo");
        creerAdministrateur("Pierro", "pierre", "pierre");
        creerAdministrateur("Wesh", "claver", "claver");
        creerAdministrateur("Administrateur", "admin", "admin");



    }

    // on veut supprimer un compte courant
    public void supprimerCompte(CompteCourant compte) {
        em.remove(em.merge(compte));
    }

    // on veut supprimer un client
    public void supprimerClient(Client client) {
        getEm().remove(getEm().merge(client));

    }

    /** 
     * 
     * 
     * 
     * les opérations
     * 
     * 
     * 
     * */
    // utilise
    public void ajouterArgent(CompteCourant cb, double argent) {
        if (cb.ajoutArgent(argent)) {
            OperationBancaire op = new OperationBancaire("Crédit", argent);

            cb.getOperations().add(op);
            em.merge(cb);
        }

    }

    public void ajouterArgentCompteEpargne(CompteEpargne cb, double argent) {
        if (cb.ajoutArgent(argent)) {

            OperationBancaire op = new OperationBancaire("Crédit", argent);
            cb.getListeOperationsCE().add(op);
            em.merge(cb);

        }

    }

    // utilise
    public void retirerArgent(CompteCourant cb, double argent) {
        if (cb.retirerArgent(argent)) {
            OperationBancaire op = new OperationBancaire("Débit", -argent);

            cb.getOperations().add(op);
            em.merge(cb);
        }

    }

    public void retirerArgentCE(CompteEpargne ce, double argent) {
        if (ce.retirerArgent(argent)) {
            OperationBancaire op = new OperationBancaire("Débit", -argent);

            ce.getListeOperationsCE().add(op);
            em.merge(ce);
        }

    }

    public void transfererArgent(CompteCourant emetteur, CompteCourant destinataire, double argent) {
        if (argent > 0) {
            if (emetteur.getId() != destinataire.getId()) {
                if (emetteur.retirerArgent(argent)) {
                    destinataire.ajoutArgent(argent);
                    OperationBancaire op1 = new OperationBancaire("Transfert argent", -argent);
                    emetteur.getOperations().add(op1);
                    OperationBancaire op2 = new OperationBancaire("Transfert argent", argent);
                    destinataire.getOperations().add(op2);
                    em.merge(emetteur);
                    em.merge(destinataire);
                } else {
                    System.err.println("Transfert impossible car l'émetteur n'a pas la somme requise");
                }


            } else {
                System.err.println("Vous ne pouvez pas transférer d'argent de votre compte pour vous même, "
                        + "le destinataire doit être un autre compte");
            }
        } else {
            System.err.println("La somme à transférer est négative ou nulle");
        }

    }

    // transfert d'argent : compteCOurant ==> compteEpargne
    public void transfererArgentClient(Long idEmetteur, Long idRecepteur, double solde) {


        if ((getCompteById(idEmetteur) != null) && (getCompteEpargneById(idRecepteur) != null)) {
            CompteCourant compteCourant = getCompteById(idEmetteur);
            CompteEpargne compteEpargne = getCompteEpargneById(idRecepteur);


            if (compteCourant.getSoldeCompte() < solde) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "", "Fonds insuffisants !"));
            } else {
                retirerArgent(compteCourant, solde);
                ajouterArgentCompteEpargne(compteEpargne, solde);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "", "Transfert effectué!!"));
            }

        } else {

            if ((getCompteById(idRecepteur) != null) && (getCompteEpargneById(idEmetteur) != null)) {

                CompteCourant compteCourant = getCompteById(idRecepteur);
                CompteEpargne compteEpargne = getCompteEpargneById(idEmetteur);

                if (compteEpargne.getSoldeCompte() < solde) {
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "", "Fonds insuffisants !"));
                } else {
                    retirerArgentCE(compteEpargne, solde);
                    ajouterArgent(compteCourant, solde);
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "", "Transfert effectué!!"));

                }
            }
        }
    }

    // on cree un nouveau client et on l'associe a un compte courant
    public Client creerClient(String nom, String prenom, String adresse, String login, String password, double solde) {
        CompteCourant compteCourant = creerCompte(solde);

        Client client = new Client(nom, prenom, adresse, login, password, compteCourant);
        //compteCourant.setClient(client);
        em.persist(compteCourant);
        em.persist(client);
        return client;
    }

    // un client existe, on lui associe un compte epargne
    public CompteEpargne associerCompteEpargneClient(Long id, double solde, double taux) {
        Client client = chercherClient(id);

        CompteEpargne compteEpargne = new CompteEpargne(solde, taux);

        OperationBancaire op = new OperationBancaire("creation du compte", solde);

        compteEpargne.getListeOperationsCE().add(op);

        client.getListeCompteEpargne().add(compteEpargne);

        em.persist(client);
        em.persist(compteEpargne);

        return compteEpargne;
    }

    public void persist(Object object) {
        em.persist(object);
    }

    /***************
     * 
     * 
     *  Compte Epargne
     * 
     * 1 client cree tjrs associe avec 1 compte courant
     * 1 client peut avoir 1 ou plusieurs comptes epargnes
     * 
     * 
     * *************/
    /////// on cree un nouveau compte epargne
    public void creerCompteEpargne(double solde, double taux) {
        CompteEpargne compteEpargne = new CompteEpargne(solde, taux);
        persist(compteEpargne);
    }

    // méthode de test pr creer plusieurs compte epargne
    public void creerCompteEpargneTest() {
        creerCompteEpargne(12, 2.3);
        creerCompteEpargne(23, 0.9);
    }

    // retourne tous les compte epargne de la BD
    public List<CompteEpargne> afficherListeCompteEpargne() {
        Query query = em.createQuery(" SELECT a FROM CompteEpargne a ");
        return query.getResultList();

    }

    // retourne tous les clients de la BD
    public List<Client> afficherClients() {
        Query query = em.createQuery(" SELECT a FROM Client a ");
        return query.getResultList();

    }

    public List<Administrateur> afficherAdministrateur() {
        Query query = em.createQuery(" SELECT a FROM Administrateur a ");
        return query.getResultList();

    }

    public Client chercherClient(Long id) {
        Client client = em.find(Client.class, id);
        return client;
    }

    // virement concerne 2 clients differents, et c'est entre les comptes courants
    public void effectuerVirement(Long idEmetteur, Long idClientRecepteur, double montant) {

        try {

            Client clientEmetteur = chercherClient(idEmetteur);
            Client clientRecepteur = chercherClient(idClientRecepteur);


            CompteCourant compteEmetteur = clientEmetteur.getCompteCourant();
            CompteCourant compteRecepteur = clientRecepteur.getCompteCourant();

            // on enleve montant dans compteEmetteur
            retirerArgent(compteEmetteur, montant);

            // on ajoute montant dans compteRecepteur
            ajouterArgent(compteRecepteur, montant);

        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "", idEmetteur + "  n'existe pas!!"));
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "", idClientRecepteur + "  n'existe pas!!"));


        }


    }

    public Client trouverClient(String login, String password) {



        Query q = em.createQuery("Select u from Client u where u.login = :login and u.password = :password");
        q.setParameter("login", login);
        q.setParameter("password", password);


        return (Client) q.getSingleResult();

    }

    public Client findClientParNomPrenom(String nom, String prenom) {



        Query q = em.createQuery("Select u from Client u where u.nom = :nom and u.prenom = :prenom");
        q.setParameter("nom", nom);
        q.setParameter("prenom", prenom);


        return (Client) q.getSingleResult();

    }

    public Administrateur trouverAdministrateur(String login, String password) {



        Query q = em.createQuery("Select u from Administrateur u where u.login = :login and u.password = :password");
        q.setParameter("login", login);
        q.setParameter("password", password);


        return (Administrateur) q.getSingleResult();

    }

    public EntityManager getEm() {
        return em;
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }

    /// l'administrateur
    public Administrateur creerAdministrateur(String nom, String login, String password) {
        Administrateur administrateur = new Administrateur(nom, login, password);

        em.persist(administrateur);
        return administrateur;
    }
}